/* License
 * 
 * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  
 *  * Redistribution of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 * 
 *  * Redistribution in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *  
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *  
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility. 
 */
package br.com.betioli.jme.games.sokobob;

import br.com.betioli.jme.games.sokobob.i18n.Messages;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

/**
 * Classe de entrada da aplicação. Um pacote.jar pode ter vários MIDlets, os 
 * quais aparecerão no dispositivos móveis como aplicações separadas.
 * 
 * @author Alexandre Parra Betioli
 */
public class SokoBobMIDlet extends MIDlet implements CommandListener {

    private MenuList menu;
    private InstructionsAlert info;
    private AboutAlert about;
    private WinnerAlert win;
    private SokoBobCanvas gameCanvas;
    private static SokoBobMIDlet instance;

    public SokoBobMIDlet() {
        instance = this;

        Messages.initLocalizationSupport();
        
        menu = new MenuList();
        menu.setCommandListener(this);
        
        loadGame();
    }

    /**
     * Método estático que retorna a instância atual do MIDlet em execução.
     * utilizado para acesso ao display em outras classes com o objetivo de
     * lançar telas de alerta por exemplo.
     */
    public static SokoBobMIDlet getInstance() {
        return instance;
    }

    /**
     * Método invocado no início da aplicação e/ou ao retornar do estado pausado.
     */
    public void startApp() {
        Display.getDisplay(this).setCurrent(menu);
    }

    /**
     * Método invocado ao receber uma chamada/ligação.
     */
    public void pauseApp() {
        System.gc();
    }

    /**
     * Ao terminar a aplicação, pára o jogo e libera objetos para coleta de lixo. 
     */
    public void destroyApp(boolean unconditional) {
        if (gameCanvas != null) {
            gameCanvas.stop();
        }
        info = null;
        about = null;
        win = null;
        gameCanvas = null;
        menu = null;

        System.gc();
    }

    /**
     * Método da interface CommandListener. Define o tratamento dos comandos do jogo.
     * 
     * Recebe como parâmetro o comando e a tela corrente. Dependendo da tela,
     * um comando pode ser tratado de diferentes maneiras. Neste caso deixaremos
     * de forma simples.
     */
    public void commandAction(Command command, Displayable dsp) {

        switch (command.getCommandType()) {

            case Command.EXIT: {
                destroyApp(true);
                notifyDestroyed();
                break;
            }

            case Command.CANCEL: {
                gameCanvas.restartLevel();
                break;
            }

            case Command.STOP: {
                gameCanvas.stop();
                menu.addContinue();
                Display.getDisplay(this).setCurrent(menu);
                break;
            }

            case Command.BACK: {
                Display.getDisplay(this).setCurrent(menu);
                break;
            }

            case Command.ITEM: {
                String selectedItem = menu.getString(menu.getSelectedIndex());

                if (selectedItem.equals(Messages.getMessage("newgame"))) {
                    gameCanvas.newGame();
                    gameCanvas.start();

                    Display.getDisplay(this).setCurrent(gameCanvas);
                    menu.removeContinue();

                }
                else if (selectedItem.equals(Messages.getMessage("continue"))) {
                    gameCanvas.start();
                    
                    Display.getDisplay(this).setCurrent(gameCanvas);
                    menu.removeContinue();

                }
                else if (selectedItem.equals(Messages.getMessage("instructions-title"))) {
                    showInstructionsAlert();

                }
                else if (selectedItem.equals(Messages.getMessage("about-title"))) {
                    showAboutAlert();
                }
                else if (selectedItem.equals(Messages.getMessage("command-exit"))) {
                    destroyApp(true);
                    notifyDestroyed();
                }

                break;
            }
            
            default: {
                /*
                 Caso não for nenhum dos tipos acima
                 */
            }
        }
    }

    /**
     * Carrega a tela principal do jogo
     */
    private void loadGame() {
        if (gameCanvas == null) {

            //Tela principal do jogo
            gameCanvas = new SokoBobCanvas();

            //Define objeto que tratará os comandos da tela atual.
            //Por padrão, os comandos serão sempre tratados no MIDlet.
            gameCanvas.setCommandListener(this);
        }
    }

    public void showInstructionsAlert() {
        if (info == null) {
            info = new InstructionsAlert();
            info.setCommandListener(this);
        }
        Display.getDisplay(this).setCurrent(info);
    }

    public void showAboutAlert() {
        if (about == null) {
            about = new AboutAlert();
            about.setCommandListener(this);
        }
        
        about.update();
        Display.getDisplay(this).setCurrent(about);
    }

    public void showWinnerAlert() {
        //if (win != null) {
            win = new WinnerAlert();
            win.setCommandListener(this);
        //}
        Display.getDisplay(this).setCurrent(win);
        Display.getDisplay(this).vibrate(500);
    }
}